package com.labofjet.common.log.appender;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.Layout;
import com.labofjet.common.aop.LogAspect;
import com.labofjet.common.dto.LogDto;
import com.labofjet.common.service.MqService;
import com.labofjet.common.util.JSONUtils;
import com.labofjet.common.util.SpringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.context.ConfigurableApplicationContext;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 向message queue发送日志的appender
 *
 * @param <E>
 */
public class RabbitMqAppender<E> extends AppenderBase<ILoggingEvent> {

	private MqService mqService;
	private boolean springInit = false;
	private String routingKey; // 日志发送到的路由键
	private String exchangeName; // 日志发送到的exchange

	private Layout<ILoggingEvent> layout;

	@Override
	protected void append(ILoggingEvent loggingEvent) {
		if (!springInit) { // 初始化中
			ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringUtils.getApplicationContext();
			if (configurableApplicationContext == null) {
				return;
			}
			if (!configurableApplicationContext.isActive()) {
				return;
			}
			MqService bean = configurableApplicationContext.getBean(MqService.class);
			if (bean == null) {
				return;
			}
			mqService = bean;
			springInit = true;
		} else {
			LogDto logDto = LogAspect.getLogDto(loggingEvent);
			if (logDto == null) { // 同步方式
				logDto = LogAspect.getLogDto();
			}
			logDto.setMessage(layout.doLayout(loggingEvent));
			logDto.setLevel(loggingEvent.getLevel().toString());
			logDto.setThreadName(loggingEvent.getThreadName());
			logDto.setDate(DateFormatUtils.format(loggingEvent.getTimeStamp(), "yyyy-MM-dd HH:mm:ss.SSS"));
			try {
				logDto.setIp(InetAddress.getLocalHost().getHostAddress());
			} catch (UnknownHostException e) {
				LogAspect.clean(loggingEvent);
				throw new RuntimeException("获取本机IP失败", e);
			}
			LogAspect.clean(loggingEvent);
			mqService.sendMessage(exchangeName, routingKey, JSONUtils.dtoToString(logDto));
		}
	}

	public String getRoutingKey() {
		return routingKey;
	}

	public void setRoutingKey(String routingKey) {
		this.routingKey = routingKey;
	}

	public Layout getLayout() {
		return layout;
	}

	public void setLayout(Layout layout) {
		this.layout = layout;
	}

	public String getExchangeName() {
		return exchangeName;
	}

	public void setExchangeName(String exchangeName) {
		this.exchangeName = exchangeName;
	}
}
